package com.freeter.luceneUtil;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.analysis.fr.FrenchAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
/*import org.apache.lucene.index.IndexWriter.MaxFieldLength;
*/import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import com.freeter.model.lucene.Article;

/**
 * Lucene第一个例子
 * 
 * @author AdminTC
 */
public class Test {
	/**
	 * 创建索引库 将Aritcle对象放入索引库中的原始记录表中，从而形成词汇表
	 */
	 
	public void createIndexDB() throws Exception {
		// 创建Article对象
		
		// 创建Document对象
		Document document = new Document();
		// 将Article对象中的三个属性值分别绑定到Document对象中
		/*
		 * 参数一：document对象中的属性名叫xid，article对象中的属性名叫id，项目中提倡相同
		 * 参数二：document对象中的属性xid的值，与article对象中相同 参数三：是否将xid属性值存入由原始记录表中转存入词汇表
		 * Store.YES表示该属性值会存入词汇表 Store.NO表示该属性值不会存入词汇表 项目中提倡非id值都存入词汇表
		 * 参数四：是否将xid属性值进行分词算法 Index.ANALYZED表示该属性值会进行词汇拆分
		 * Index.NOT_ANALYZED表示该属性值不会进行词汇拆分 项目中提倡非id值都进行词汇拆分
		 * 目前将分词理解为分汇拆分，目前认为一个汉字一个分词拆分
		 */
		 
		Article article = new Article(1234567, "培训abac", "123456789IT家咖啡馆");
		 
		document.add(new Field("xid", article.getId().toString(), TextField.TYPE_STORED));
		document.add(new Field("xtitle", article.getTitle(), TextField.TYPE_STORED));
		document.add(new Field("xcontent", article.getContent(), TextField.TYPE_STORED));
		// 创建IndexWriter字符流对象
		
		 /* 参数一：lucene索引库最终应对于硬盘中的目录，例如：E:/IndexDBDBDB
		 * 参数二：采用什么策略将文本拆分，一个策略就是一个具体的实现类
		 * 参数三：最多将文本拆分出多少词汇，LIMITED表示1W个，即只取前1W个词汇，如果不足1W个词汇个，以实际为准
		 */
		Directory directory = FSDirectory.open(new File("E:/Index").toPath());
		Version version = Version.LUCENE_7_1_0;
		Analyzer analyzer = new StandardAnalyzer();

		IndexWriterConfig config = new IndexWriterConfig(analyzer);
		IndexWriter iwriter = new IndexWriter(directory, config);
		// 将document对象写入lucene索引库
		iwriter.addDocument(document);
		// 关闭IndexWriter字符流对象
		iwriter.close();
	}

	/**
	 * 根据关键字从索引库中搜索符合条件的内容
	 */ 
	//@org.junit.Test
	public void findIndexDB() throws Exception {
		// 准备工作
		String keywords = "a";
		List<Article> articleList = new ArrayList<Article>();
		Directory directory = FSDirectory.open(Paths.get("E:/Index"));
		DirectoryReader ireader = DirectoryReader.open(directory);
		//Analyzer analyzer = new StandardAnalyzer();
		 
		Analyzer analyzer =new FrenchAnalyzer();
		//testAnalyzer(new StandardAnalyzer(LuceneUtil.getVersion()),"传智播客说我们的首都是北京呀it");
		//testAnalyzer(new FrenchAnalyzer(LuceneUtil.getVersion()),"传智播客说我们的首都是北京呀it");
		//testAnalyzer(new RussianAnalyzer(LuceneUtil.getVersion()),"传智播客说我们的首都是北京呀it");
		//testAnalyzer(new ChineseAnalyzer(),"传智播客说我们的首都是北京呀it");
		//testAnalyzer(new CJKAnalyzer(LuceneUtil.getVersion()),"传智播客说我们的首都是北京呀it");
		//testAnalyzer(new CJKAnalyzer(LuceneUtil.getVersion()),"传智是一家IT培训机构");
		//testAnalyzer(new FrenchAnalyzer(LuceneUtil.getVersion()),"传智是一家how are you培训机构");
		// 创建IndexSearcher字符流对象
		IndexSearcher indexSearcher = new IndexSearcher(ireader);
		// 创建查询解析器对象
	 
		QueryParser queryParser = new  QueryParser("xcontent", analyzer);

		// 创建对象对象封装查询关键字
		Query query = queryParser.parse(keywords);
		// 根据关键字，去索引库中的词汇表搜索
		
		/* * 参数一：表示封装关键字查询对象，其它QueryParser表示查询解析器
		 * 参数二：MAX_RECORD表示如果根据关键字搜索出来的内容较多，只取前MAX_RECORD个内容
		 * 不足MAX_RECORD个数的话，以实际为准*/
		 
		int MAX_RECORD = 100;
		TopDocs topDocs = indexSearcher.search(query, MAX_RECORD);
		// 迭代词汇表中符合条件的编号
		for (int i = 0; i < topDocs.scoreDocs.length; i++) {
			// 取出封装编号和分数的ScoreDoc对象
			ScoreDoc scoreDoc = topDocs.scoreDocs[i];
			// 取出每一个编号，例如:0,1,2
			int no = scoreDoc.doc;
			// 根据编号去索引库中的原始记录表中查询对应的document对象
			Document document = indexSearcher.doc(no);
			// 获取document对象中的三个属性值
			String xid = document.get("xid");
			String xtitle = document.get("xtitle");
			String xcontent = document.get("xcontent");
			// 封装到artilce对象中
			Article article = new Article(Integer.parseInt(xid), xtitle, xcontent);
			// 将article对象加入到list集合中
			articleList.add(article);
		}
		// 迭代结果集
		for (Article a : articleList) {
			System.out.println(a);
		}
	}
 /**
    * 对特定项搜索
    *  按词条搜索—TermQuery
     *TermQuery是最简单、也是最常用的Query。TermQuery可以理解成为“词条搜索”，
    * 在搜索引擎中最基本的搜索就是在索引中搜索某一词条，而TermQuery就是用来完成这项工作的。
     * 在Lucene中词条是最基本的搜索单位，从本质上来讲一个词条其实就是一个名/值对。
    * 只不过这个“名”是字段名，而“值”则表示字段中所包含的某个关键字。
    * @throws Exception
    */
	//@org.junit.Test
	   public void testTermQuery()throws Exception{
		Directory directory = FSDirectory.open(Paths.get("E:/IndexDBDBDB"));
		DirectoryReader ireader = DirectoryReader.open(directory);
		Analyzer analyzer = new StandardAnalyzer();
		List<Article> articleList = new ArrayList<Article>();
		
		// 创建IndexSearcher字符流对象
		IndexSearcher indexSearcher = new IndexSearcher(ireader);
		// 创建查询解析器对象
	      String searchField="xcontent";
	      String q="I";
	      Term t=new Term(searchField,q);
	      Query query=new TermQuery(t);
	      TopDocs topDocs=indexSearcher.search(query, 10);
	      System.out.println("匹配 '"+q+"'，总共查询到"+topDocs.totalHits+"个文档");
	     
	      for(ScoreDoc scoreDoc:topDocs.scoreDocs){
	         Document doc=indexSearcher.doc(scoreDoc.doc);
	        // System.out.println(doc.get("fullPath"));
	      }
	      
	      System.out.println(123);
	   }
	   
	   
	  @org.junit.Test
	   public   void getWords(){  
		  //Analyzer analyzer = new StandardAnalyzer();
		  //Analyzer analyzer =  new FrenchAnalyzer();
		  //Analyzer analyzer =  new SimpleAnalyzer();
		  Analyzer analyzer = new WhitespaceAnalyzer();
		  // Analyzer analyzer =  new EnglishAnalyzer();
		 // Analyzer analyzer =  new CJKAnalyzer();
		 // Analyzer analyzer =  new RussianAnalyzer();
		    List<String> result = new ArrayList<String>();  
		    TokenStream stream = null;  
		    try {
		    	
		        stream = analyzer.tokenStream("content", new StringReader("124213123eqdsf大范甘迪df!@#$"));  
		        CharTermAttribute attr = stream.addAttribute(CharTermAttribute.class);  
		        stream.reset();  
		        while(stream.incrementToken()){  
		            result.add(attr.toString());  
		            System.out.println(attr.toString());
		        }  
		    } catch (IOException e) {  
		        e.printStackTrace();  
		    }finally{  
		        if(stream != null){  
		            try {  
		                stream.close();  
		            } catch (IOException e) {  
		                e.printStackTrace();  
		            }  
		        }  
		    }  
		  //  return result;  
		}  
	   
	   //@org.junit.Test
	   public void custom() throws Exception{
		   PatternAnalyzer analyzer=new PatternAnalyzer(";"); //要注意文本中的符号是中文的还是英文的
		 //空字符串代表单字切分
		 TokenStream ts = analyzer.tokenStream("field", new StringReader("123456789"));
		 CharTermAttribute term=ts.addAttribute(CharTermAttribute.class);
		 ts.reset();
		 while(ts.incrementToken()){
		 String x = term.toString();
		 System.out.println(x);
		 }
		 ts.end();
		 ts.close();
		 }
	    
}
